// Copyright (C) 2018 - 2019, Yongming Li <l@pear.hk>
// bitcoin-cli getnewaddress "accountname"
// http://fm4dd.com/openssl/eckeycreate.htm


#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <stdbool.h>

#include "pear_key.h"
#include "pear_debug.h"
#include "serialization/tpl.h"


// secp256k1:
// const unsigned int PRIVATE_KEY_SIZE = 279;
// const unsigned int PUBLIC_KEY_SIZE  = 65;
// const unsigned int SIGNATURE_SIZE   = 72;




static int64 nMockTime = 0;  // For unit testing
EC_KEY* pkey=NULL;



int64 GetTime()
{
    if (nMockTime) return nMockTime;

    return time(NULL);
}

inline int64 GetPerformanceCounter()
{
    int64 nCounter = 0;
    struct timeval t;
    gettimeofday(&t, NULL);
    nCounter = t.tv_sec * 1000000 + t.tv_usec;
    return nCounter;
}

void RandAddSeedPerfmon()
{
    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64 nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();
}


void GenerateNewKey()
{
    RandAddSeedPerfmon();
    
    pkey = pear_MakeNewKey();
    pear_GetPubKey(pkey);
    pear_GetPrivKey(pkey);
    return;
    //return key.GetPubKey();
}

void get_pubkey_from_sig()
{
    EC_KEY* pkey = pear_MakeNewKey();
    if (pkey == NULL)
            printf("EC_KEY_new_by_curve_name failed\r\n");

    char hash[33]={0x00};
    //hash[2]=0x01;
    char sig[256]={0x00};
    if(pear_signCompact(hash, 32, sig ,pkey))
    {
        printf("sing successful! \r\n");
    }
    pear_GetPubKey(pkey);
    EC_KEY* pkey_pub = EC_KEY_new_by_curve_name(NID_secp256k1);
    //pear_GetPubKey(pkey_pub);
    pear_SetCompactSignature(hash, 32, sig,65,pkey_pub);
    pear_GetPubKey(pkey_pub);
    
}

//CBitcoinAddress address(newKey);

void unserialization()
{

    tpl_node *tn;
    int id;
    char *name;

    tn = tpl_map("A(is)", &id, &name);
    tpl_load(tn, TPL_FILE, "account.tpl");

    while ( tpl_unpack(tn,1) > 0 ) {
        printf("id %d, user %s\n", id, name);
        free(name);
    }
    tpl_free(tn);
}
void serialization()
{
    tpl_node *tn;
    int id=0;
    char *name, *names[] = { "joe", "bob", "cary" };

    tn = tpl_map("A(is)", &id, &name);

    for(name=names[0]; id < 3; name=names[++id]) {
        tpl_pack(tn,1);
    }

    tpl_dump(tn, TPL_FILE, "account.tpl");
    tpl_free(tn);
    unserialization();
}
void test_key()
{
    char vchPubKey[1024]  = {0x00};
    char vchPrivKey[1024] = {0x00};

    EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (pkey == NULL)
            printf("EC_KEY_new_by_curve_name failed\r\n");

    pear_get_keystore(vchPrivKey,279);
    printf("dump  key from key.dat file\r\n");

    pear_hex_dump(vchPrivKey,279);

    if (pear_SetPrivKey(pkey,vchPrivKey,279))
    {
        printf("Set privkey succues! \r\n ");
    }

    pear_GetPubKey(pkey);
    return pkey;
}

int main()
{

    printf("Welcome PRCToken! \r\n");
    //get_pubkey_from_sig();
    test_key();
    //GenerateNewKey();
    return 0;
}
